package uimigration.WidgetsModel.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.eclipse.emf.ecore.util.EcoreUtil;

import uimigration.Interactions.Behaviour;
import uimigration.Interactions.EditContent;
import uimigration.WidgetsModel.APIModel;
import uimigration.WidgetsModel.Widget;

public class WidgetsModelManager {
	private boolean DEBUG=false;
	private APIModel apiModel;
	public WidgetsModelManager (APIModel newModel)
	{
		apiModel= newModel;
		
	}
	
	//Found all widgets that have equivalent behaviors or more
	public List<Widget> findEquivalentWidgets(Widget widget){
		List<Widget> foundW=new ArrayList<Widget>();
		for(Widget wi: apiModel.getContains()){
			if(widget.isIsRoot() && wi.isIsRoot())
				foundW.add(wi);
			else 
				if( !widget.isIsRoot()&& !wi.isIsRoot())
					if(wi.isIsContainer()==widget.isIsContainer() && wi.getContainsWidgetLength()<=0 && widget.getContainsWidgetLength()<=0)
					{	
						if(wi.getBehavior().size()>=widget.getBehavior().size())
							if(equivalentWidget(widget, wi))
								foundW.add(wi);
					}
					else if(wi.getContainsWidgetLength()>0 &&  widget.getContainsWidgetLength()<=0 )
					{
						for (Widget w : wi.getContainsWidget()){
							if(w.isIsContainer()==widget.isIsContainer()){
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(equivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}
							}
							else if(wi.isIsContainer())
							{
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(equivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}								
							}
						}
					}
					else if (wi.getContainsWidgetLength()>0 &&  widget.getContainsWidgetLength()>0 )
					{
						for(Widget wci : widget.getContainsWidget())
						{
							for (Widget w : wi.getContainsWidget()){
								if(w.isIsContainer()== wci.isIsContainer()){
									if(w.getBehavior().size()>=wci.getBehavior().size())
										if(equivalentWidget(wci, w))
											{
												foundW.add(wi);
												break;
											}
								}
								else if(wi.isIsContainer())
								{
									if(w.getBehavior().size()>=widget.getBehavior().size())
										if(equivalentWidget(widget, w))
											{
												foundW.add(wi);
												break;
											}								
								}

							}
							if(foundW.size()>0)
								break;
						}
					}
					else if((wi.getContainsWidgetLength()<=0 &&  widget.getContainsWidgetLength()>0 ))
					{
						for (Widget w : widget.getContainsWidget()){
							if(w.isIsContainer()==widget.isIsContainer()){
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(equivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}
							}
						}

					}
		}
		if(foundW!=null && DEBUG)
			System.out.println("Test findEquivalentWidgets: "+testFind(widget, foundW));
		return foundW;	
	}
	
	//Found all widgets that have equivalent behaviors or more
	public List<Widget> findTypeEquivalentWidgets(Widget widget){
		if(DEBUG)
			System.out.println("findTypeEquivalentWidgets: w="+ widget.toString() +" "+widget.getBehavior().toString());
		List<Widget> foundW=new ArrayList<Widget>();
		for(Widget wi: apiModel.getContains()){
			if(widget.isIsRoot() && wi.isIsRoot())
				foundW.add(wi);
			else 
				if( !widget.isIsRoot()&& !wi.isIsRoot())
					if(wi.isIsContainer()==widget.isIsContainer() && wi.getContainsWidgetLength()<=0 && widget.getContainsWidgetLength()<=0)
					{	
						if(wi.getBehavior().size()>=widget.getBehavior().size())
							if(typeEquivalentWidget(widget, wi))
								foundW.add(wi);
					}
					else if(wi.getContainsWidgetLength()>0 &&  widget.getContainsWidgetLength()<=0 )
					{
						for (Widget w : wi.getContainsWidget()){
							if(w.isIsContainer()==widget.isIsContainer()){
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(typeEquivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}
							}
							else if(wi.isIsContainer())
							{
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(typeEquivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}								
							}
						}
					}
					else if (wi.getContainsWidgetLength()>0 &&  widget.getContainsWidgetLength()>0 )
					{
						for(Widget wci : widget.getContainsWidget())
						{
							for (Widget w : wi.getContainsWidget()){
								if(w.isIsContainer()== wci.isIsContainer()){
									if(w.getBehavior().size()>=wci.getBehavior().size())
										if(typeEquivalentWidget(wci, w))
											{
												foundW.add(wi);
												break;
											}
								}
								else if(wi.isIsContainer())
								{
									if(w.getBehavior().size()>=widget.getBehavior().size())
										if(typeEquivalentWidget(widget, w))
											{
												foundW.add(wi);
												break;
											}								
								}

							}
							if(foundW.size()>0)
								break;
						}
					}
					else if((wi.getContainsWidgetLength()<=0 &&  widget.getContainsWidgetLength()>0 ))
					{
						for (Widget w : widget.getContainsWidget()){
							if(w.isIsContainer()==widget.isIsContainer()){
								if(w.getBehavior().size()>=widget.getBehavior().size())
									if(typeEquivalentWidget(widget, w))
										{
											foundW.add(wi);
											break;
										}
							}
						}

					}
		}
		if(foundW!=null && DEBUG)
			System.out.println("Test findEquivalentWidgets: "+testFind(widget, foundW));
		return foundW;	
	}
	
	//Found all widgets that have equal behavior
	public List<Widget> findEqualWidget(Widget widget){
		List<Widget> foundW= new ArrayList<Widget>();
		for(Widget wi: apiModel.getContains()){
			if( !widget.isIsRoot()&& !wi.isIsRoot())
				if(wi.isIsContainer()==widget.isIsContainer() && wi.getContainsWidgetLength()<1)
				{	
					if(wi.getBehavior().size()>=widget.getBehavior().size())
						if(equalityWidget(widget, wi))
							foundW.add(wi);
				}
				else if(wi.getContainsWidgetLength()>0)
				{
					for (Widget w : wi.getContainsWidget()){
						if(w.isIsContainer()==widget.isIsContainer()){
							if(w.getBehavior().size()==widget.getBehavior().size())
								if(equalityWidget(widget, w))
								{	
									foundW.add(wi);
									break;
								}

						}
					}
				}
				else if (wi.getContainsWidgetLength()>0 &&  widget.getContainsWidgetLength()>0 )
				{
					for(Widget wc : widget.getContainsWidget())
					{
						for (Widget w : wi.getContainsWidget()){
							if(w.isIsContainer()==wc.isIsContainer()){
								if(w.getBehavior().size()>=wc.getBehavior().size())
									if(equalityWidget(wc, w))
										{
											foundW.add(wi);
											break;
										}
							}
						}
						if(foundW.size()>0)
							break;
					}
				}
		}
		if(foundW!=null && DEBUG)
			System.out.println("Test findEqualWidget: "+testFind(widget, foundW));
		return foundW;
	}

	//Test if tow widgets are equivalents w1.size()<w2.size()
	public boolean equivalentWidget(Widget w1, Widget w2){
		boolean equal=true;

		int found=w1.getBehavior().size();
		for(Behaviour b1: w1.getBehavior()){
			for(Behaviour b2:w2.getBehavior())
				if(equalBehaviour(b1,b2) )
				{	
					found--;
					break;
				}
		}
		if(DEBUG)
			System.out.println("equivalentWidget found="+found+" w1.Behavior="+w1.getBehavior()+" w2.Behavior="+w2.getBehavior() +" w2="+w2.toString());
		if(found>0 && !equivalentProperties(w1, w2))
			equal=false;
		return equal;
	}
	private boolean equivalentProperties(Widget ws, Widget wt)
	{
		for(uimigration.WidgetsModel.Property ps: ws.getProperties())
		{
			for(uimigration.WidgetsModel.Property pt: wt.getProperties())
			{
				if(ps.getRenderingProperty()!=null && pt.getRenderingProperty()!=null)
				{
					if(ps.getDataType().compareTo(pt.getDataType())==0)
						return true;
				}
			}
		}
		return false;
	}
	
	public boolean typeEquivalentWidget(Widget w1, Widget w2)
	{
		Vector<String> v1,v2;
		v1=getWidgetClass(w1);
		v2=getWidgetClass(w2);
		return v1.contains(v2);
	}
	
	private Vector<String> getWidgetClass (Widget w){
		
		Vector <String> vec= new Vector<String>();
		for(int i=0; i<w.getBehavior().size();i++)
		{
			vec.add(getBehaviorType(w.getBehavior().get(i)));
		}
		return vec;
	}
	
	private String getBehaviorType(Behaviour b)
	{
		if(b.getClass().getSimpleName().contains("Activate"))
			return "Link";
		else if(b.getClass().getSimpleName().contains("Content"))
			return "Content";
		else 
			return "Render";
	}
	
	//Test if tow widgets are equals base on their behaviors
	public boolean equalityWidget(Widget w1, Widget w2){
		boolean equal=false;
		int found=w1.getBehavior().size();
		if(found==0)
			found=w2.getBehavior().size();
		for(Behaviour b1: w1.getBehavior()){
			for(Behaviour b2:w2.getBehavior())
				if(equalBehaviour(b1, b2))
				{	
					found--;
					break;
				}
		}
		if(found==0)
			equal=true;
		return equal;
	}
	
	private boolean equalBehaviour(Behaviour b1, Behaviour b2){
		boolean equal=false;
		if(b1.getClass().getSimpleName().equals(b2.getClass().getSimpleName()))
		{
			try
			{
				Behaviour bc1 = null,bc2= null;
				if(b1.eIsProxy())
				{	
					EcoreUtil.resolve(b1, bc1);
					bc1= b1;
					EcoreUtil.resolveAll(b1);
					bc1=b1;
				}
				else 
					bc1=b1;
				if(b2.eIsProxy())
					EcoreUtil.resolve(b2, bc2);
				else
					bc2= b2;
				if(((EditContent)bc1).getEditatbleContent().size()>0 && ((EditContent)bc2).getEditatbleContent().size()>0 && ((EditContent)bc1).getEditatbleContent().get(0).getHasType()==((EditContent)bc2).getEditatbleContent().get(0).getHasType())
					equal= true;
				else if(((EditContent)b1).getEditatbleContent().size()==0 && ((EditContent)b2).getEditatbleContent().size()==0)
					equal= true;
				equal= false;
			}catch(ClassCastException e){
			}
			equal=true;
		}
		return equal;
	}
	
	public String testFind(Widget looking,List<Widget> found)
	{
		String ret="";
		ret+="Looking for :"+looking.getName()+" "+looking.getId()+"\n";
		for(Behaviour b:looking.getBehavior())
			ret+="-"+b.getClass().getSimpleName()+"\n";
		ret+="Found :\n";
		for(Widget w:found){
			ret+="+"+w.getName()+" "+w.getId()+"\n";
			for(Behaviour bi:w.getBehavior())
				ret+=bi.getClass().getSimpleName()+"\n";
		}
		
		return ret;
	}
	

}
